package com.kepler.social.domain.support.sms;

import com.kepler.social.common.Before;
import com.kepler.social.common.Time;
import com.kepler.social.common.constants.BusinessState;
import com.kepler.social.common.constants.RedisKeyConst;
import com.kepler.social.common.constants.TipsConst;
import com.kepler.social.common.exception.ServiceException;
import com.kepler.social.common.utils.RandomUtil;
import com.kepler.social.common.utils.StringExtendsUtils;
import com.kepler.social.common.utils.ValidateAssert;
import com.kepler.social.generic.SmsHelper;
import com.kepler.social.common.rule.SmsRule;
import jakarta.annotation.Nullable;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Objects;


/**
 短信发送
 1、基础的短信发送支持，属于业务支撑
 2、短信发送系统，可以将短信模板配置到这里，短信发送系统调用短信发送支持完成功能
 3、业务系统，再短信发送系统中配置短信模板，后传入参数完成发送功能。
 */
@Service
@Slf4j
public class SmsBo {

    @Resource
    private SmsHelper smsHelper;
    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private RedissonClient redissonClient;


    /**
     * 发送手机验证码
     *
     * @param countryCallingCode 国际区号
     * @param mobilePhoneNumber  手机号码
     * @param timeout            验证码的有效时限
     * @param before             发送之前进行的操作
     */
    public void sendMobilePhoneCaptcha(Integer countryCallingCode, Long mobilePhoneNumber, Time timeout,
                                       @Nullable Before before) {
        log.info("sendMobilePhoneCaptcha param phoneNumber {} expireTimeCaptcha {} unit {}", mobilePhoneNumber,
                timeout.getTime(), timeout.getUnit());
        ValidateAssert.isTrue(StringExtendsUtils.isMobilePhoneNumber(mobilePhoneNumber + ""), TipsConst.incorrect_mobile_phone_format);
        String lockKey = RedisKeyConst.PHONE_CAPTCHA_LOCK_PREFIX + mobilePhoneNumber;
        final RLock lock = redissonClient.getLock(lockKey);
        try {
            boolean res = lock.tryLock();
            if (!res) {
                log.info("sendRetrievePasswordMobilePhoneCaptcha duplicate_requests phoneNumber {}", mobilePhoneNumber);
                throw new ServiceException(BusinessState.DUPLICATE_REQUESTS);
            }
            if(Objects.nonNull(before)){
                before.before();
            }
            this.sendSmsCaptcha(SmsRule.defaultCcc(countryCallingCode), mobilePhoneNumber, timeout);
        } finally {
            if (null != lock && lock.isLocked()) { // 是否还是锁定状态
                if (lock.isHeldByCurrentThread()) {//是否是当前执行线程的锁
                    lock.unlock(); // 释放锁
                }
            }
        }
    }

    /**
     * 发送短信验证码
     *
     * @param mobilePhoneNumber
     */
    public void sendSmsCaptcha(int countryCallingCode, long mobilePhoneNumber, Time timeout) {
        int captcha = RandomUtil.generateRandomNumber(4);
        String context = String.format("【开普勒】您好，您的验证码是:%s,有效期%s分钟。", captcha, timeout.toMinutes());
        redisTemplate.opsForValue()
                .set(RedisKeyConst.PHONE_CAPTCHA_PREFIX + countryCallingCode + "_" + mobilePhoneNumber,
                        captcha, timeout.getTime(), timeout.getUnit());
        smsHelper.sendSms(mobilePhoneNumber + "", context);
        log.info("SmsCaptcha phoneNumber {} context {}", mobilePhoneNumber, context);
    }

    public void verifySmsCaptcha(int countryCallingCode, long mobilePhoneNumber, int captcha, boolean del) {
        String key = RedisKeyConst.PHONE_CAPTCHA_PREFIX + countryCallingCode + "_" + mobilePhoneNumber;
        Integer captchaCached = (Integer) redisTemplate.opsForValue().get(key);
        ValidateAssert.notNull(captchaCached, TipsConst.captcha_expire);
        ValidateAssert.isTrue(captcha == captchaCached, TipsConst.captcha_mismatching);
        if (del) {
            redisTemplate.delete(key);
        }
        log.info("verifySmsCaptcha phoneNumber {} captcha {}", mobilePhoneNumber, captcha);
    }

    // TODO send
    public void sendRegisterSuccessSms(int countryCallingCode, long mobilePhoneNumber, String password, String encryptedPassword) {
        log.info("sendRegisterSuccessSms phoneNumber {} encryptedPassword {}", mobilePhoneNumber, encryptedPassword);
    }

    // TODO send
    public void sendPasswordResetSuccessSms(int countryCallingCode, long mobilePhoneNumber, String password, String encryptedPassword) {
        log.info("sendRegisterSuccessSms phoneNumber {} encryptedPassword {}", mobilePhoneNumber, encryptedPassword);
    }

    // TODO send
    public void sendPasswordChangeSuccessSms(int countryCallingCode, long mobilePhoneNumber, String password, String encryptedPassword) {
        log.info("sendRegisterSuccessSms phoneNumber {} encryptedPassword {}", mobilePhoneNumber, encryptedPassword);
    }

}